小弟我查的資料不多,對於未來web component可能會出現的新技術只有查到Declarative Shadow DOM。
SPA技術很好用,因為用Javascript來建構頁面時,開發和使用者互動的功能很簡單。可是因為SPA是完全由javascript生成頁面,對SEO非常不友好,所謂的Isomorphic JavaScript技術也相應而生。而web component也因為是使用javascript來建構custom element和shadow DOM,基本上SPA會有的問題web component都會有,所以在SEO的問題上,也可以使用相同的思路來處理。
Isomorphic JavaScript的核心我認為有二部分,第一部分是在伺服端就做出HTML,第二部分則是在前端載入JS後的hydration(注水)。
Declarative Shadow DOM現在只能在Chrome系列的瀏覧器上使用,其他瀏覧器不會生成DOM
Can i use 支援表 https://caniuse.com/declarative-shadow-dom
shadowroot這個屬性可以告訴瀏覧器,template元素和內容在生成DOM時是要渲染成Shadow DOM;當然,對那些不支援shadowroot屬性的瀏覧器來說,template元素還是會跳過不渲染。
shadowroot="open"就像是使用this.attachShadow({mode: 'open'})一樣
<my-com id="my-com" card-content="ha! you~" content-color="yellow">
<template shadowroot="open">
<style>
...
</style>
<div class='card'>
<h2 id='card-title' class='card-title'>title</h2>
<div id='card-content' class='card-content'>content</div>
<slot id='card-slot'></slot>
<div id='card-content2' class='card-content2'>content2</div>
</div>
</template>
<div id="slot">click</div>
</my-com>
如果有支援Declarative Shadow DOM,在使用class時可以不用使用attachShadow方法生成SHadow DOM(因為己經在解析HTML時生成了),但事件的綁定之類的還是要宣告。
class MyComponent extends HTMLElement {
constructor() {
super();
this.render = this.render.bind(this);
this.ClickEvent = this.ClickEvent.bind(this);
this.ClickEvent2 = this.ClickEvent2.bind(this);
// 如果在不支援Declarative Shadow DOM的瀏覧器中使用要加這一段
// 因為有支援的話this.shadowRoot就不會是null
if (!this.shadowRoot) {
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(this.render())
}
}
connectedCallback() {
// 不管有沒有支援Declarative Shadow DOM都要加這一段,因為事件綁定只能由JS來做
// javascript 的 hydration
this.root.getElementById('card-title').addEventListener('click', this.ClickEvent)
this.root.getElementById('card-slot').addEventListener('click', this.ClickEvent2)
}
disconnectedCallback() {
// 不管有沒有支援Declarative Shadow DOM都要加這一段,因為事件綁定只能由JS來做
// javascript 的 hydration
this.root.getElementById('card-title').removeEventListener('click', this.ClickEvent)
this.root.getElementById('card-slot').removeEventListener('click', this.ClickEvent2)
}
...
// 如果有支援Declarative Shadow DOM,就可以不需要這個函式
render() {
const template = document.createElement('template');
template.innerHTML = `
<style>${this.style}</style>
<div class='card'>
<h2 id='card-title' class='card-title'>title</h2>
<div id='card-content' class='card-content'>content</div>
<slot id='card-slot'></slot>
<div id='card-content2' class='card-content2'>content2</div>
</div>
`;
return template.content;
}
ClickEvent() {
console.log('click')
}
ClickEvent2() {
const newEvevt = new CustomEvent('clickSlot', {
bubbles: true,
composed: true,
detail: {
name: 'click'
}
})
this.dispatchEvent(newEvevt)
}
}
customElements.define('my-com', MyComponent);